import { 
  generateRoomId, 
  generatePlayerId, 
  validateRoomName, 
  validatePlayerName,
  getSafeRoomData,
  getSafePlayerData 
} from '../utils/helpers.js';
import logger from '../utils/logger.js';

class RoomManager {
  constructor(databaseService) {
    this.db = databaseService;
    this.rooms = new Map(); // 内存中的房间缓存
    this.playerRooms = new Map(); // 玩家ID -> 房间ID的映射
  }

  /**
   * 创建房间
   */
  async createRoom(roomName, hostPlayerName) {
    try {
      // 验证输入
      const roomNameValidation = validateRoomName(roomName);
      if (!roomNameValidation.valid) {
        return { success: false, message: roomNameValidation.message };
      }

      const playerNameValidation = validatePlayerName(hostPlayerName);
      if (!playerNameValidation.valid) {
        return { success: false, message: playerNameValidation.message };
      }

      // 生成唯一的房间ID（尝试最多10次避免重复）
      let roomId;
      let attempts = 0;
      const maxAttempts = 10;
      
      do {
        roomId = generateRoomId();
        attempts++;
        
        // 检查房间ID是否已存在
        const existingRoom = await this.db.getRoomById(roomId);
        if (!existingRoom) {
          break; // ID可用，退出循环
        }
        
        if (attempts >= maxAttempts) {
          return { success: false, message: '生成房间ID失败，请重试' };
        }
      } while (attempts < maxAttempts);

      const hostPlayerId = generatePlayerId();

      const roomData = {
        id: roomId,
        name: roomName,
        hostId: hostPlayerId,
        hostName: hostPlayerName,
        status: 'waiting',
        playerCount: 1,
        maxPlayers: 3,
        gameConfig: {
          gameMode: 'standard',
          autoStart: false
        },
        createdAt: new Date()
      };

      // 保存到数据库
      await this.db.createRoom(roomData);

      // 缓存到内存
      const roomWithPlayers = {
        ...roomData,
        players: [{
          id: hostPlayerId,
          name: hostPlayerName,
          seatIndex: 0,
          isReady: false,
          status: 'online',
          joinedAt: new Date()
        }]
      };

      this.rooms.set(roomId, roomWithPlayers);
      this.playerRooms.set(hostPlayerId, roomId);

      logger.info(`房间创建成功: ${roomId} by ${hostPlayerName}`);

      return { 
        success: true, 
        data: {
          room: getSafeRoomData(roomWithPlayers),
          player: {
            id: hostPlayerId,
            name: hostPlayerName,
            isHost: true
          }
        }
      };
    } catch (error) {
      logger.error(`创建房间失败: ${error.message}`);
      return { success: false, message: '服务器内部错误' };
    }
  }

  /**
   * 加入房间
   */
  async joinRoom(roomId, playerName) {
    try {
      // 验证输入
      if (!roomId || typeof roomId !== 'string') {
        return { success: false, message: '无效的房间ID' };
      }

      const playerNameValidation = validatePlayerName(playerName);
      if (!playerNameValidation.valid) {
        return { success: false, message: playerNameValidation.message };
      }

      // 先从数据库获取最新房间信息
      const roomFromDb = await this.db.getRoomById(roomId);
      if (!roomFromDb) {
        return { success: false, message: '房间不存在' };
      }

      if (roomFromDb.status !== 'waiting') {
        return { success: false, message: '房间游戏已开始，无法加入' };
      }

      if (roomFromDb.player_count >= roomFromDb.max_players) {
        return { success: false, message: '房间已满' };
      }

      // 检查玩家名称是否已存在
      const existingPlayer = roomFromDb.players.find(p => p.name === playerName);
      if (existingPlayer) {
        return { success: false, message: '该名称已被使用' };
      }

      const playerId = generatePlayerId();

      // 添加到数据库
      await this.db.joinRoom(roomId, playerId, playerName);

      // 重新从数据库获取完整房间信息
      const updatedRoom = await this.db.getRoomById(roomId);
      
      // 更新内存缓存
      this.rooms.set(roomId, updatedRoom);
      this.playerRooms.set(playerId, roomId);

      const joinedPlayer = updatedRoom.players.find(p => p.id === playerId);

      logger.info(`玩家加入房间: ${playerName} -> ${roomId}`);

      return { 
        success: true, 
        data: {
          room: getSafeRoomData(updatedRoom),
          player: {
            id: playerId,
            name: playerName,
            isHost: false,
            seatIndex: joinedPlayer.seatIndex
          }
        }
      };
    } catch (error) {
      logger.error(`加入房间失败: ${error.message}`);
      return { success: false, message: error.message.includes('已满') ? error.message : '服务器内部错误' };
    }
  }

  /**
   * 离开房间
   */
  async leaveRoom(playerId) {
    try {
      const roomId = this.playerRooms.get(playerId);
      if (!roomId) {
        return { success: false, message: '您不在任何房间中' };
      }

      // 从数据库删除玩家
      const remainingPlayerCount = await this.db.leaveRoom(playerId, roomId);

      // 更新内存缓存
      this.playerRooms.delete(playerId);

      if (remainingPlayerCount === 0) {
        // 房间为空，从内存中删除
        this.rooms.delete(roomId);
        logger.info(`房间已删除: ${roomId}`);
        return { success: true, roomDeleted: true };
      } else {
        // 重新从数据库获取房间信息
        const updatedRoom = await this.db.getRoomById(roomId);
        if (updatedRoom) {
          this.rooms.set(roomId, updatedRoom);
        }
        
        logger.info(`玩家离开房间: ${playerId} from ${roomId}`);
        
        return { 
          success: true, 
          data: {
            room: updatedRoom ? getSafeRoomData(updatedRoom) : null
          }
        };
      }
    } catch (error) {
      logger.error(`离开房间失败: ${error.message}`);
      return { success: false, message: '服务器内部错误' };
    }
  }

  /**
   * 切换准备状态
   */
  async toggleReady(playerId, isReady) {
    try {
      const roomId = this.playerRooms.get(playerId);
      if (!roomId) {
        return { success: false, message: '您不在任何房间中' };
      }

      const room = this.rooms.get(roomId);
      if (!room) {
        return { success: false, message: '房间不存在' };
      }

      if (room.status !== 'waiting') {
        return { success: false, message: '游戏已开始，无法更改准备状态' };
      }

      // 房主不需要准备，房主决定开始游戏
      if (room.hostId === playerId) {
        return { success: false, message: '房主无需准备，请直接开始游戏' };
      }

      // 更新数据库
      await this.db.updatePlayerReady(playerId, roomId, isReady);

      // 更新内存缓存
      const player = room.players.find(p => p.id === playerId);
      if (player) {
        player.isReady = isReady;
      }

      logger.info(`玩家准备状态更新: ${playerId} -> ${isReady}`);

      return { 
        success: true, 
        data: {
          room: getSafeRoomData(room)
        }
      };
    } catch (error) {
      logger.error(`更新准备状态失败: ${error.message}`);
      return { success: false, message: '服务器内部错误' };
    }
  }

  /**
   * 添加AI玩家补位
   */
  async addAIPlayer(hostPlayerId) {
    try {
      const roomId = this.playerRooms.get(hostPlayerId);
      if (!roomId) {
        return { success: false, message: '您不在任何房间中' };
      }

      const room = this.rooms.get(roomId);
      if (!room) {
        return { success: false, message: '房间不存在' };
      }

      if (room.hostId !== hostPlayerId) {
        return { success: false, message: '只有房主可以添加AI玩家' };
      }

      if (room.status !== 'waiting') {
        return { success: false, message: '游戏已开始，无法添加AI玩家' };
      }

      if (room.players.length >= room.maxPlayers) {
        return { success: false, message: '房间已满' };
      }

      // 生成AI玩家信息
      const aiPlayerNames = ['智能玩家Alpha', '智能玩家Beta', '智能玩家Gamma'];
      const existingNames = room.players.map(p => p.name);
      const availableName = aiPlayerNames.find(name => !existingNames.includes(name));
      
      if (!availableName) {
        return { success: false, message: '已达到AI玩家数量限制' };
      }

      const aiPlayerId = 'ai_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);

      // 添加到数据库
      await this.db.joinRoom(roomId, aiPlayerId, availableName, true); // 第四个参数标识AI玩家

      // 重新从数据库获取房间信息
      const updatedRoom = await this.db.getRoomById(roomId);
      if (updatedRoom) {
        this.rooms.set(roomId, updatedRoom);
        this.playerRooms.set(aiPlayerId, roomId);
      }

      logger.info(`AI玩家添加: ${availableName} -> ${roomId}`);

      return { 
        success: true, 
        data: {
          room: getSafeRoomData(updatedRoom),
          aiPlayer: {
            id: aiPlayerId,
            name: availableName,
            isAI: true
          }
        }
      };
    } catch (error) {
      logger.error(`添加AI玩家失败: ${error.message}`);
      return { success: false, message: '服务器内部错误' };
    }
  }

  /**
   * 检查是否可以开始游戏 - 支持AI玩家
   */
  canStartGame(roomId) {
    const room = this.rooms.get(roomId);
    if (!room) {
      logger.warn(`检查游戏开始条件失败: 房间不存在 ${roomId}`);
      return { canStart: false, message: '房间不存在' };
    }
    
    if (room.status !== 'waiting') {
      logger.warn(`检查游戏开始条件失败: 房间状态不正确 ${roomId} (${room.status})`);
      return { canStart: false, message: '房间状态不正确' };
    }

    if (room.players.length < 3) {
      logger.warn(`检查游戏开始条件失败: 玩家人数不足 ${roomId} (${room.players.length}/3)`);
      return { canStart: false, message: '玩家人数不足，需要3人' };
    }

    // 检查除房主外的所有真人玩家是否都已准备（AI玩家自动准备）
    const nonHostHumanPlayers = room.players.filter(p => p.id !== room.hostId && !p.isAI);
    const allReady = nonHostHumanPlayers.every(p => p.isReady);

    if (!allReady) {
      const notReadyPlayers = nonHostHumanPlayers.filter(p => !p.isReady);
      logger.warn(`检查游戏开始条件失败: 有玩家未准备 ${roomId}`, notReadyPlayers.map(p => p.name));
      return { canStart: false, message: '还有玩家未准备' };
    }

    logger.info(`游戏开始条件检查通过: ${roomId}`);
    return { canStart: true };
  }

  /**
   * 开始游戏
   */
  async startGame(hostPlayerId) {
    try {
      logger.info(`开始游戏请求: 房主 ${hostPlayerId}`);
      
      const roomId = this.playerRooms.get(hostPlayerId);
      if (!roomId) {
        logger.warn(`开始游戏失败: 房主 ${hostPlayerId} 不在任何房间中`);
        return { success: false, message: '您不在任何房间中' };
      }

      const room = this.rooms.get(roomId);
      if (!room) {
        logger.warn(`开始游戏失败: 房间 ${roomId} 不存在`);
        return { success: false, message: '房间不存在' };
      }

      if (room.hostId !== hostPlayerId) {
        logger.warn(`开始游戏失败: ${hostPlayerId} 不是房间 ${roomId} 的房主 (实际房主: ${room.hostId})`);
        return { success: false, message: '只有房主可以开始游戏' };
      }

      logger.info(`检查房间 ${roomId} 游戏开始条件`);
      const canStartCheck = this.canStartGame(roomId);
      if (!canStartCheck.canStart) {
        logger.warn(`开始游戏失败: ${canStartCheck.message}`);
        return { success: false, message: canStartCheck.message };
      }

      // 更新房间状态
      logger.info(`更新房间状态: ${roomId} -> playing`);
      await this.db.updateRoomStatus(roomId, 'playing');
      room.status = 'playing';

      logger.info(`游戏开始成功: ${roomId}`);

      return { 
        success: true, 
        data: {
          room: getSafeRoomData(room)
        }
      };
    } catch (error) {
      logger.error(`开始游戏失败: ${error.message}`);
      return { success: false, message: '服务器内部错误' };
    }
  }

  /**
   * 获取房间信息
   */
  async getRoomById(roomId) {
    try {
      // 先从内存缓存获取
      let room = this.rooms.get(roomId);
      
      // 如果缓存中没有，从数据库获取
      if (!room) {
        room = await this.db.getRoomById(roomId);
        if (room) {
          this.rooms.set(roomId, room);
        }
      }

      return room ? getSafeRoomData(room) : null;
    } catch (error) {
      logger.error(`获取房间信息失败: ${error.message}`);
      return null;
    }
  }

  /**
   * 更新房间状态
   */
  async updateRoomStatus(roomId, status) {
    try {
      await this.db.updateRoomStatus(roomId, status);
      
      // 同时更新内存缓存
      const room = this.rooms.get(roomId);
      if (room) {
        room.status = status;
      }
      
      return { success: true };
    } catch (error) {
      logger.error(`更新房间状态失败: ${error.message}`);
      return { success: false, message: '服务器内部错误' };
    }
  }

  /**
   * 获取可用房间列表
   */
  async getAvailableRooms(limit = 20) {
    try {
      logger.info(`正在查询可用房间，限制: ${limit}`);
      const rooms = await this.db.getAvailableRooms(limit);
      logger.info(`数据库返回房间数: ${rooms.length}`);
      
      const result = rooms.map(room => ({
        id: room.id,
        name: room.name,
        playerCount: room.playerCount,
        maxPlayers: room.maxPlayers,
        createdAt: room.createdAt
      }));
      
      logger.info(`处理后返回房间数: ${result.length}`);
      return result;
    } catch (error) {
      logger.error(`获取可用房间失败: ${error.message}`);
      logger.error(`错误堆栈: ${error.stack}`);
      throw error; // 改为抛出错误而不是返回空数组
    }
  }

  /**
   * 更新玩家在线状态
   */
  async updatePlayerStatus(playerId, status, socketId = null) {
    try {
      const roomId = this.playerRooms.get(playerId);
      if (!roomId) {
        return false;
      }

      await this.db.updatePlayerStatus(playerId, roomId, status, socketId);

      // 更新内存缓存
      const room = this.rooms.get(roomId);
      if (room) {
        const player = room.players.find(p => p.id === playerId);
        if (player) {
          player.status = status;
          if (socketId !== null) {
            player.socketId = socketId;
          }
        }
      }

      return true;
    } catch (error) {
      logger.error(`更新玩家状态失败: ${error.message}`);
      return false;
    }
  }

  /**
   * 获取玩家所在房间ID
   */
  getPlayerRoomId(playerId) {
    return this.playerRooms.get(playerId);
  }

  /**
   * 清理过期数据
   */
  async cleanup() {
    try {
      await this.db.cleanupExpiredData();
      
      // 清理内存缓存中的过期数据
      const now = Date.now();
      const expiredRooms = [];
      
      for (const [roomId, room] of this.rooms.entries()) {
        // 清理创建超过2小时且无玩家的房间
        if (room.players.length === 0 && 
            (now - new Date(room.createdAt).getTime()) > 2 * 60 * 60 * 1000) {
          expiredRooms.push(roomId);
        }
      }
      
      for (const roomId of expiredRooms) {
        this.rooms.delete(roomId);
        logger.info(`清理过期房间: ${roomId}`);
      }
      
    } catch (error) {
      logger.error(`房间清理失败: ${error.message}`);
    }
  }

  /**
   * 获取房间统计信息
   */
  getStats() {
    return {
      totalRooms: this.rooms.size,
      totalPlayers: this.playerRooms.size,
      playingRooms: Array.from(this.rooms.values()).filter(r => r.status === 'playing').length,
      waitingRooms: Array.from(this.rooms.values()).filter(r => r.status === 'waiting').length
    };
  }
}

export default RoomManager;